use std::sync::{Arc, LazyLock};

use crate::error::*;
use arc_swap::ArcSwapOption;
use hashbrown::HashMap;
use parking_lot::RwLock;

use crate::config::ssl::acceptor::SslAcceptorRuntimeConf;

use super::site_conf::{HttpAddressSiteRuntimeConf, HttpSiteRuntimeConf};

pub struct HttpSiteRuntimeConfManager {
    map: RwLock<HashMap<String, Arc<HttpSiteRuntimeConf>>>,
    default: ArcSwapOption<HttpSiteRuntimeConf>,
}

#[allow(dead_code)]
impl HttpSiteRuntimeConfManager {
    pub fn get_instance() -> &'static HttpSiteRuntimeConfManager {
        static HTTP_SITE_RUNTIME_CONF_MANAGER: LazyLock<
            HttpSiteRuntimeConfManager,
        > = LazyLock::new(|| HttpSiteRuntimeConfManager {
            map: RwLock::new(HashMap::with_capacity(256)),
            default: ArcSwapOption::new(None),
        });
        &HTTP_SITE_RUNTIME_CONF_MANAGER
    }

    pub fn add_site_conf(mut domain: String, conf: Arc<HttpSiteRuntimeConf>) {
        let instance = Self::get_instance();

        domain = domain.to_ascii_lowercase();

        if domain == "*" {
            instance.default.store(Some(conf));
            return;
        }

        instance.map.write().insert(domain, conf);
    }

    // FIXME: host修改成&[u8]类型?
    pub fn lookup_address_site_conf(
        host: &str,
        listener_address: &[u8],
    ) -> Result<Option<Arc<HttpAddressSiteRuntimeConf>>> {
        let instance = Self::get_instance();

        // 查询全域名
        let res =
            instance.lookup_address_site_conf_helper(host, listener_address);
        if let Some(c) = res {
            return Ok(Some(c));
        }

        // TODO: 查询泛域名逻辑待实现.

        Ok(None)
    }
}

impl HttpSiteRuntimeConfManager {
    fn lookup_address_site_conf_helper(
        &self,
        domain: &str,
        listener_address: &[u8],
    ) -> Option<Arc<HttpAddressSiteRuntimeConf>> {
        if domain.as_bytes().eq_ignore_ascii_case(b"*") {
            let site_conf = self.default.load().clone();
            if let Some(site_conf) = site_conf {
                return self.lookup_address_site_conf_helper_by_listener_addr(
                    &site_conf,
                    listener_address,
                );
            }

            return None;
        }

        let read_guard = self.map.read();
        if let Some(site_conf) = read_guard.get(domain) {
            return self.lookup_address_site_conf_helper_by_listener_addr(
                site_conf,
                listener_address,
            );
        }

        None
    }

    fn lookup_address_site_conf_helper_by_listener_addr(
        &self,
        site_conf: &Arc<HttpSiteRuntimeConf>,
        listener_address: &[u8],
    ) -> Option<Arc<HttpAddressSiteRuntimeConf>> {
        for v in site_conf.address_runtime_conf_vec.iter() {
            for vv in &v.listen_on {
                if *vv == "all" {
                    return Some(v.clone());
                }

                if listener_address.eq_ignore_ascii_case(vv.as_bytes()) {
                    return Some(v.clone());
                }
            }
        }

        None
    }
}

#[inline]
pub fn get_address_site_conf(
    host: &str,
    listener_address: &[u8],
) -> Result<Option<Arc<HttpAddressSiteRuntimeConf>>> {
    HttpSiteRuntimeConfManager::lookup_address_site_conf(host, listener_address)
}

pub fn get_ssl_acceptor_conf(
    sni: Option<&String>,
    listener_address: &str,
) -> Result<Option<Arc<SslAcceptorRuntimeConf>>> {
    let sni = match sni {
        Some(sni) => sni,

        // 没有sni, 返回默认配置.
        None => "*",
    };

    get_address_site_conf(sni, listener_address.as_bytes())
        .map(|option_c| option_c.map(|c| c.ssl_acceptor_runtime_conf.clone()))
}
